﻿using System;
using JamesZhao.Engine.Graphics.Effects;
using JamesZhao.Engine.Graphics.Geometry;
using JamesZhao.Engine.Graphics.Surfaces;
using JamesZhao.Engine.Graphics.Visuals;
using SlimDX.DXGI;
using SlimMath;

namespace JamesZhao.Engine.Graphics.RenderStages
{
    internal class DownsampleStage : RenderStage
    {
        public ColorSurface Source { get; set; }
        public ColorSurface Target { get; set; }

        public DownsampleStage(GraphicsDevice device)
        {
            DownsampleEffect = new GpuProgram(device, "Shaders/Downsample.fx");


            var quadGeom = new GeometryBuffer(device);
            quadGeom.InitializeFrom(MeshData.LoadFullScreenQuad());
            FullScreenQuad = new MeshDrawable
            {
                GeometryBuffer = quadGeom
            };
        }

        protected MeshDrawable FullScreenQuad { get; set; }

        protected GpuProgram DownsampleEffect { get; set; }

        public override string Name
        {
            get { return "Downsample"; }
        }

        public DownsampleStage PreviousDownsample { get; set; }
        public Vector2 ResolvedSize { get; set; }
        protected override void OnRender(GraphicsDevice device, SwapChain swapChain, VisualsList visualsList, Camera camera)
        {
            device.ImmediateContext.ClearRenderTargetView(Target.TargetView, new Color4(0, 0, 0, 0));

            device.ImmediateContext.OutputMerger.SetTargets(
                new[]
                    {
                        Target.TargetView
                    });
            var previousSize = PreviousDownsample == null
                                 ? new Vector2(Source.ActualSize.Width, Source.ActualSize.Height) 
                                 : PreviousDownsample.ResolvedSize ;

            var targetSize = previousSize/2;
            targetSize = new Vector2((float) Math.Ceiling(targetSize.X), (float) Math.Ceiling(targetSize.Y));

            var textureSize = new Vector2(Source.ActualSize.Width, Source.ActualSize.Height);


            DownsampleEffect.VectorVariables["targetSize"].Set(targetSize);
            DownsampleEffect.VectorVariables["previousSize"].Set(previousSize);
            DownsampleEffect.VectorVariables["textureSize"].Set(textureSize);

            DownsampleEffect.ResourceVariables["srcTexture"].SetResource(Source.ResourceView);

            device.ImmediateContext.OutputMerger.SetTargets(Target.TargetView);
            FullScreenQuad.RenderWithGpuProgram(device, camera, DownsampleEffect);

            ResolvedSize = targetSize;
        }
    }
}